home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-05-04 | 8.9 KB | 383 lines | [TEXT/PCXT] |
- Path: ooc.uva.nl!hp4nl!mcsun!uunet!crdgw1!uakari.primate.wisc.edu!sdd.hp.com!elroy.jpl.nasa.gov!ncar!gatech!udel!haven.umd.edu!ni.umd.edu!ni.umd.edu!zben
- From: zben@ni.umd.edu (Ben Cranston)
- Newsgroups: comp.sys.mac.programmer
- Subject: MPW tool to patch resources or files
- Keywords: MPW Patch
- Message-ID: <1991Apr27.010549.20391@ni.umd.edu>
- Date: 27 Apr 91 01:05:49 GMT
- Sender: usenet@ni.umd.edu (USENET News System)
- Organization: University of Maryland at College Park
- Lines: 369
- Nntp-Posting-Host: ni.umd.edu
-
- There were some simple example MPW tools in this month's MacTutor. I had
- never realized it was that easy to write a tool! Here is a tool that can
- be used to "patch" a resource or a data fork with either inline hex data,
- the contents of another resource, or the contents of another data fork.
- For example, the "command-F" patches for LaserWriter 6.0.1 can be done
- with this command:
-
- Patch LaserWriter PDEF(125) <command-d>
- $c78:51 $c7c:50 $c84:50 $c8c:51 $c9a:50 $e9e:6038 $1860:60
-
- Some of the diagnostics are a bit wrong but I think a diagnostic is given
- for every error case. Also there is some debug printout you can take out
- when you trust it. There is a neat hex dump routine buried in here too!
-
-
- /* MPW tool to "Patch" data or resource fork of file
- *
- * For usage notes see below...
- *
- * Ben Cranston <zben@ni.umd.edu>
- * University of Maryland at College Park
- * 910419
- */
-
- #include <CType.h>
- #include <ErrMgr.h>
- #include <Files.h>
- #include <Memory.h>
- #include <Resources.h>
- #include <StdIO.h>
- #include <String.h>
-
- #define P(x) fprintf(stderr,"%s%s\n",progname,x);
- #define Q(x) fprintf(stderr,"%s\n",x);
-
- char *progname;
-
- usage()
- {
- P(": Usage: ")
- P(" file offset:hexdata ")
- P(" file offset infile inoffset:length ")
- P(" file offset infile resource ")
- Q("");
- P(" file resource offset:hexdata ")
- P(" file resource offset infile inoffset:length ")
- P(" file resource offset infile resource ")
- Q("");
- Q("where resource is restype(resnum) or restype@resname ")
- }
-
- /*
- * Test for valid hexadecimal digit.
- */
-
- #define ishex(x) (isascii(x)&&isxdigit(x))
-
- /*
- * Integer value (0-15) for hexadecimal digit.
- */
-
- #define toint(x) ((x)<='9'?(x)-'0':(x)<='F'?(x)-'A'+10:(x)-'a'+10)
-
- /*
- * Print out system string for a particular error code.
- */
-
- syserr(short errcode)
- {
- char errmsg[256];
-
- GetSysErrText(errcode,errmsg);
- fprintf(stderr,"# %s\n",errmsg);
- }
-
- /*
- * Diagnose syntax error on call to this tool.
- */
-
- syntax(char *s)
- {
- fprintf(stderr,"%s - %s\n",progname,s);
- exit(1);
- }
-
- /*
- * Diagnose file access problems.
- */
-
- cant(char *diag, char *fname, short errcode)
- {
- fprintf(stderr,"# %s - Can't %s : %P\n",progname,diag,fname);
- syserr(errcode);
- exit(2);
- }
-
- /*
- * Show arguments to this program.
- */
-
- dumpargs(int argc, char **argv)
- {
- short i;
-
- fprintf(stderr,"argc = %d\n",argc);
- for (i=0 ; i<argc; i++)
- fprintf(stderr,"argv[%d] = \"%s\"\n",i,argv[i]);
- }
-
- /*
- * Dump area in hexadecimal and readable formats.
- */
-
- hexdump(int num, char *buf)
- {
- short rx,cx;
- char chr;
- char vr[17];
-
- for ( rx=0 ; rx<num ; rx+=16 ) {
- fprintf(stderr,"%03X ",rx);
- for ( cx=0 ; cx<16 ; cx++ ) {
- if ( (rx+cx) < num ) {
- chr = buf[rx+cx];
- fprintf(stderr,"%02X ",chr&0xFF);
- vr[cx] = (isascii(chr)&&isprint(chr))?chr:'.';
- } else {
- fprintf(stderr," ");
- vr[cx] = ' ';
- }
- }
- vr[16] = 0;
- fprintf(stderr," %s\n",vr);
- }
- }
-
- /*
- * Scan and convert integer, either decimal or $hex.
- */
-
- int getnum(char *s, char t)
- {
- int acc = 0;
- short sign = 1;
-
- if ('$' == (*s)) {
- s++;
- while ( ishex(*s) ) {
- acc = (acc<<4) | toint(*s);
- s++;
- }
- } else {
- if ('-' == (*s)) {
- s++;
- sign = -1;
- }
- while ( (isascii(*s)&&isdigit(*s)) ) {
- acc = 10*acc + (*s) - '0';
- s++;
- }
- acc = sign*acc;
- }
-
- if (t!=0) {
- if (t!=(*s))
- syntax("missing field terminator");
- else
- s++;
- }
-
- if (*s)
- syntax("bad character in integer field");
- return(acc);
- }
-
- /*
- * Scan a resource designator and read in the designaged resource.
- * This is called both to get resource data for a patch source
- * and to get in a resource that is itself to be patched.
- *
- * Formats are:
- * PDEF(125)
- * $50444546(125) # same, but restype specified in hex
- * PDEF@resourcename # resource designated by name rather than number
- */
-
- short
- getres(char *fname, char *sfield, short perms, short *rfnum, Handle *rshand)
- {
- char *sp;
- short which, rsnum, status;
- OSType rstype;
- char buffer[6], rsname[256];
-
- if (sp = strchr(sfield,'(') ) {
- which = 1;
- rsnum = getnum(sp+1,')');
- } else if (sp = strchr(sfield,'@') ) {
- which = 0;
- rsname[0] = strlen(sp+1);
- BlockMove(sp+1,&rsname[1],rsname[0]);
- } else
- return(0);
-
- (*sp) = 0;
- if ('$' == (*sfield) )
- rstype = getnum(sfield,0);
- else if (4 >= (status = sp-sfield) ) {
- rstype = (OSType) ' ';
- BlockMove(sfield,(char *)&rstype,status);
- } else
- syntax("bad resource type field");
-
- SetResLoad(false);
- (*rfnum) = OpenRFPerm(fname,0,perms);
- SetResLoad(true);
- if (0 > (*rfnum) )
- cant("open (resource fork of) file",fname,ResError());
-
- if (which)
- (*rshand) = Get1Resource(rstype,rsnum);
- else
- (*rshand) = Get1NamedResource(rstype,rsname);
-
- if (0 == (*rshand) ) {
- *(OSType *)&buffer = rstype;
- buffer[4] = 0;
- if (which)
- fprintf(stderr,"# %s - Can't load resource : %P %s %d\n",
- progname,fname,buffer,rsnum);
- else
- fprintf(stderr,"# %s - Can't load resource : %P %s %P\n",
- progname,fname,buffer,rsname);
- if (0 == (status=ResError()) )
- fprintf(stderr,"# No ResError worth mentioning...\n");
- else
- syserr(status);
- exit(2);
- }
-
- return(1);
- }
-
- main(int argc, char **argv)
- {
- short rfnum, rrfnum, status;
- char *sp;
- int length, offset, roffset, xflen;
- char fname[256];
- char bigbuf[1024];
- Handle rshand, rrshand;
-
- /* dumpargs(argc,argv); */
- progname = argv[0];
- argc--, argv++;
- if (argc < 2) {
- usage();
- exit(1);
- }
-
- fname[0] = strlen(argv[0]);
- BlockMove(argv[0],&fname[1],fname[0]);
- /*
- * Open file (and possibly resource) to be patched
- */
- if ( getres(fname,argv[1],fsRdWrPerm,&rfnum,&rshand) )
- argc--, argv++;
- else {
- if ( 0 > (status = FSOpen(fname,0,&rfnum)) )
- cant("open (data fork of) file",fname,status);
- rshand = (Handle) 0;
- }
- argc--, argv++;
-
- do {
- /*
- * Get patch
- */
- if (0 > argc)
- syntax("missing patch field!");
- if (sp = strchr(argv[0],':') ) {
- *sp = 0;
- offset = getnum(argv[0],0);
- length = 0;
- while ( *(sp+1) ) {
- if (ishex(*(sp+1)) && ishex(*(sp+2))) {
- bigbuf[length++] =
- (toint(*(sp+1))<<4) + toint(*(sp+2));
- sp += 2;
- } else
- syntax("error in hex input data");
- }
- } else {
- offset = getnum(argv[0],0);
- argc--, argv++;
- if (0 > argc)
- syntax("missing patch file!");
- fname[0] = strlen(argv[0]);
- BlockMove(argv[0],&fname[1],fname[0]);
- if ( getres(fname,argv[1],fsRdPerm,&rrfnum,&rrshand) ) {
- length = GetHandleSize(rrshand);
- if ( sizeof(bigbuf) < length )
- syntax("resource too big!!!");
- BlockMove(*rrshand,bigbuf,length);
- CloseResFile(rrfnum);
- } else if (sp = strchr(argv[1],':') ) {
- *sp = 0;
- roffset = getnum(argv[1],0);
- length = getnum(sp+1,0);
- if (0 > (status = FSOpen(fname,0,&rrfnum)) )
- cant("open (data fork of) file",fname,status);
- if (0 > (status = SetFPos(rrfnum,fsFromStart,roffset)) )
- cant("reposition within file",fname,status);
- xflen = length;
- if (0 > (status = FSRead(rrfnum,&xflen,bigbuf)) )
- cant("read (data fork of) file",fname,status);
- if (xflen != length) {
- fprintf(stderr,"data short read %d\n",xflen);
- length = xflen;
- }
- if (0 > (status = FSClose(rrfnum)) )
- cant("close (data fork of) file",fname,status);
- } else
- syntax("missing : in offset:length field");
- argc--, argv++;
- }
- argc--, argv++;
-
- fprintf(stderr,"offset = %d\n",offset);
- fprintf(stderr,"length = %d\n",length);
- hexdump(length,bigbuf);
- /*
- * Apply patch
- */
- if (rshand) {
- if ( (offset+length) > GetHandleSize(rshand) ) {
- SetHandleSize(rshand,offset+length);
- if (noErr != (status=MemError()) ) {
- fprintf(stderr,"# Could not expand handle\n");
- syserr(status);
- exit(2);
- }
- }
- BlockMove(bigbuf,(offset+*rshand),length);
- } else {
- if (0 > (status = SetFPos(rfnum,fsFromStart,offset)) )
- cant("reposition within file",fname,status);
- xflen = length;
- if (0 > (status = FSWrite(rfnum,&xflen,bigbuf)) )
- cant("write to (data fork of) file",fname,status);
- if (xflen != length)
- fprintf(stderr,"data short write %d\n",xflen);
- }
-
- fprintf(stderr,"at end, argc = %d\n",argc);
- } while (0 < argc);
- /*
- * Close file and/or resource fork
- */
- if (rshand) {
- ChangedResource(rshand);
- CloseResFile(rfnum);
- } else {
- if (0 > (status = FSClose(rfnum)) )
- cant("close (data fork of) file",fname,status);
- }
-
- exit(0);
- }
-
-